#pragma once
#include <QObject>
#include <QUdpSocket>
#include <QHostAddress>
#include <QNetworkInterface>
#include "QsUdpGlobal.h"

/**
 * @brief UDP通信模块主类
 * 
 * 提供UDP数据包的发送和接收功能，使用单例模式。
 * 支持动态配置端口和地址，线程安全的跨线程通信。
 */
class QsUdp : public QObject
{
    Q_OBJECT
public:
    /**
     * @brief 构造函数，支持多实例
     * @param info UDP信息结构体，默认监听0.0.0.0:45454
     * @param parent 父对象
     */
    explicit QsUdp(const QsUdpInfo& info = QsUdpInfo(QHOSTADDRESS_ANY_COMPAT, 45454), QObject* parent = nullptr);
    
    /**
     * @brief 获取全局单例实例（兼容老代码）
     */
    static QsUdp* instance();
    
    /**
     * @brief 发送UDP数据包
     * @param msgType 消息类型
     * @param data 要发送的数据
     * @param r1 保留字段1，默认为0
     * @param r2 保留字段2，默认为0
     * 
     * 将数据封装成QsUdpPacket格式后发送到配置的地址和端口
     */
    void send(quint16 msgType, const QByteArray& data, quint16 r1 = 0, quint16 r2 = 0);
    
    /**
     * @brief 初始化UDP模块
     * @param info UDP信息结构体，包含端口和地址
     * 
     * 跨线程调用接收器的init方法
     */
    void init(const QsUdpInfo& info);
    
    /**
     * @brief 获取当前UDP信息
     * @return 当前UDP信息结构体
     */
    QsUdpInfo info() const { return m_info; }
    
    /**
     * @brief 设置UDP信息
     * @param info 新的UDP信息结构体
     * 
     * 如果信息有变化，会重新初始化接收器
     */
    void setInfo(const QsUdpInfo& info);
    
    /**
     * @brief 析构函数
     * 
     * 停止接收线程，清理资源，确保线程安全退出
     */
    ~QsUdp();

    /**
     * @brief 设置发送socket选项
     * @param option 选项类型
     * @param value 选项值
     * @return this，支持链式调用
     */
    QsUdp* setSocketOption(QAbstractSocket::SocketOption option, const QVariant& value);

    /**
     * @brief 设置接收socket选项
     * @param option 选项类型
     * @param value 选项值
     * @return this，支持链式调用
     */
    QsUdp* setReceiverSocketOption(QAbstractSocket::SocketOption option, const QVariant& value);

    /**
     * @brief 启用或禁用广播
     * @param enabled 是否启用广播
     * @return this，支持链式调用
     */
    QsUdp* enableBroadcast(bool enabled);

    /**
     * @brief 加入多播组
     * @param groupAddress 多播组地址
     * @param iface 网络接口，默认自动选择
     * @return 是否成功
     */
    bool joinMulticastGroup(const QHostAddress& groupAddress, const QNetworkInterface& iface = QNetworkInterface());

    /**
     * @brief 离开多播组
     * @param groupAddress 多播组地址
     * @param iface 网络接口，默认自动选择
     * @return 是否成功
     */
    bool leaveMulticastGroup(const QHostAddress& groupAddress, const QNetworkInterface& iface = QNetworkInterface());

    /**
     * @brief 从ini配置文件读取参数并设置
     * @param iniFile ini文件路径
     * @param group 配置组，默认"udp"
     */
    void setConfigFromIni(const QString& iniFile, const QString& group = "udp");

    /**
     * @brief 批量设置参数（QVariantMap）
     * @param map 参数map
     */
    void setConfig(const QVariantMap& map);

    /**
     * @brief 批量设置参数（QJsonObject）
     * @param obj 参数对象
     */
    void setConfig(const QJsonObject& obj);

signals:
    /**
     * @brief 接收到UDP数据包时发出的信号
     * @param header 包头
     * @param data 数据内容
     * @param info UDP信息结构体（IP和端口）
     */
    void received(const QsUdpPacketHeader& header, QByteArray data, const QsUdpInfo& info);

    /**
     * @brief 发生错误时发出的信号
     * @param msg 错误描述
     */
    void errorOccurred(const QString& msg);

    /**
     * @brief socket状态变化时发出的信号
     * @param state 新状态
     */
    void stateChanged(QAbstractSocket::SocketState state);

    /**
     * @brief 成功加入多播组时发出的信号
     * @param group 多播组地址
     */
    void multicastJoined(const QHostAddress& group);

    /**
     * @brief 广播功能启用/禁用时发出的信号
     * @param enabled 是否启用
     */
    void broadcastEnabled(bool enabled);

private:
    class QsUdpReceiver* m_receiver = nullptr;    ///< UDP接收器对象
    QUdpSocket* m_sender = nullptr;               ///< UDP发送socket
    QThread* m_receiverThread = nullptr;          ///< 接收器工作线程
    QsUdpInfo m_info;                             ///< 当前UDP信息
}; 